// ==================================================================================
// Shared Genomics Project MPI Codebase
// Version 1.0 30/04/2010
//
// (c) 2010 University of Manchester all rights reserved
//
// This file is distributed under the GNU General Public License, Version 2.  
// Please see the file COPYING.txt for more details
// ==================================================================================

#ifndef _LOCUS_H_
#define _LOCUS_H_

#include "types.h"

#ifdef __cplusplus
extern "C" {
#endif

#define MAX_ALLELE_NAMELENGTH 3

/*!
\file
\ingroup	gio
\brief		SNP Definition (PLINK)
\details
	A locus represents a SNP and is derived from the locus class within PLINK.<br>
	The \ref locus structure is not involved in any statistical calculation
	but is used to store data from a PLINK-compatible text input file prior to
	a format conversion or encoding operation.<br>
	This \ref locus is also used in the unit tests which validate the I/O behavior 
	of the codebase against PLINK.
*/

/*! \brief SNP Definition (PLINK) */
struct locus {
	/*! \brief Chromosome Number */
	int chr;

	/*! \brief SNP Frequency of an allele */
	double freq;

	/*! \brief Genomic position (Centi-Morgan) */
	double pos;      

	/*! \brief base-pair position */
	int bp;          

	/*! \brief Number of non-missing alleles */
	int nm;          

	/*! \brief SNP identifier (e.g. RS Number) */
	char *name;

	/*! \brief Character code of allele at position 1 */
	char allele1[MAX_ALLELE_NAMELENGTH];

	/*! \brief Character code of allele at position 2 */
	char allele2[MAX_ALLELE_NAMELENGTH];
	
	/*! \brief Flag is Genomic Variant */
	BOOL isVariant;

	/*! \brief No. 'linked' allele Names */
	int nAlleles;

	/*! \brief Linked allele Names */
	char** alleles;

	/*! \brief Array of allelic frequencies */
	VECTOR_T  freqs;

	/*! \brief No. allelic frequencies */
	int nFreqs;

	/*! \brief Keys of the acode map. */
	char **acode_map_keys;

	/*! \brief Values of the acode map. */
	int *acode_map_values;

	/*! \brief Size of the acode map. */
	int nAcode_map;

	/*! \brief Allelic variant */
	BOOL allelicVariation;

	/*! \brief Copy Number Variant (CNV) */
	BOOL copyNumberVariation;

	/*! \brief Status flag */
	BOOL integerDosage;
};

/*! 
\brief Initialise an locus structure. 
\param [in,out] loc A Locus
\return 0 on success, 1 on failure
*/
int locus_init(struct locus *loc);

/*! 
\brief %Set the name (ID) of a locus
\param [in,out] loc A Locus
\param [in] value Name/ID string
\return 0 on success, 1 on failure
*/
int locus_set_name(struct locus *loc, const char* value);

/*! 
\brief Free the attributes of a locus structure.
\param [in,out] loc A Locus
\return 0 on success, 1 on failure
*/
int locus_free_attributes(struct locus *loc);

/*! 
\brief Create an initialised locus structure
\return \ref locus on success or NULL on failure.
*/
struct locus* locus_create();

/*! 
\brief %Set the allelic character codename at position one.
\param [in,out] loc A Locus
\param [in] value The allelic character code
\return 0 on success, 1 on failure
*/
int locus_set_allele1(struct locus *loc, const char* value);

/*! 
\brief %Set the allelic character codename at position two.
\param [in,out] loc A Locus
\param [in] value The allelic character code
\return 0 on success, 1 on failure
*/
int locus_set_allele2(struct locus *loc, const char* value);

/*! 
\brief Insert an allelic Id into the allele name list.
\param [in,out] loc A Locus
\param [in] value The allelic character code
\return 0 on success, 1 on failure
\see locus::alleles
*/
int locus_insert_allele(struct locus *loc, const char* value);

/*!
\brief Locus (pointer-to-pointer) QSORT Comparison 
\returns -1 if less, zero if equal, 1 if greater.
*/
int locus_compare(const void* p1, const void* p2);

#ifdef __cplusplus
}
#endif

#endif // _LOCUS_H_
